package org.bigdata.framework.core.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.cybozu.labs.langdetect.Detector;
import com.cybozu.labs.langdetect.DetectorFactory;
import com.cybozu.labs.langdetect.LangDetectException;
import com.cybozu.labs.langdetect.Language;

/**
 * 语种识别工具
 * 
 * @author cuichao703
 *
 */
public class LangDetectUtils {

	private static final Logger LOG = Logger.getLogger(LangDetectUtils.class);

	// profiles we will load from classpath
	 static final String languages[] = { "af", "ar", "bg", "bn", "cs", "da",
	 "de", "el", "en", "es", "et", "fa", "fi",
	 "fr", "gu", "he", "hi", "hr", "hu", "id", "it", "ja", "kn", "ko", "lt",
	 "lv", "mk", "ml", "mr", "ne", "nl",
	 "no", "pa", "pl", "pt", "ro", "ru", "sk", "sl", "so", "sq", "sv", "sw",
	 "ta", "te", "th", "tl", "tr", "uk",
	 "ur", "vi", "zh-cn", "zh-tw" };
	// shorttext
	// static final String languages[] = { "en","zh-cn"};

	// 缺省返回语种
	static String fallback = "en";

	// 语种白名单
	static List<String> whiteList = Arrays.asList("zh-cn", "zh-tw", "en", "fr", "de", "it", "ja", "ko", "ru");

	/**
	 * 单语种模式识别文本
	 * 
	 * @param _text
	 * 
	 * @return 返回语种的2位简称
	 */
	public static String detectLang(String _text) {
		// 初始化语言包
		loadLangProfiles();

		String lang = fallback;
		Detector detect = null;
		try {
			detect = DetectorFactory.create();
			detect.append(_text);
			String langTemp = detect.detect();

			// 在白名单
			if (whiteList.contains(langTemp)) {
				lang = langTemp;
			}
		} catch (LangDetectException e) {
			LOG.debug(UtilConstant.PROJECT + " 文本中未发现语言特征.");
		}
		return lang;
	}

	/**
	 * 单语种模式识别文本,并包装返回,格式为en|文本内容
	 * 
	 * @param _text
	 * 
	 * @return 返回格式为 en|文本内容
	 */
	public static String detectLangAndWrap(String _text) {
		return detectLangAndWrap(_text,false);
	}
	
	public static String detectLangAndWrap(String _text,boolean isSearch) {
		String lang = detectLang(_text);
		if (StringUtils.isNotBlank(lang) && StringUtils.isNotBlank(_text)) {
			if(_text.startsWith("\"") && _text.endsWith("\"")) {
				return "\"" +  lang + "|" + _text.substring(1, _text.length()-1) + "\"";
			}else if(isSearch){
				if(_text.startsWith("(") && _text.endsWith(")")){
					_text = _text.substring(1,_text.length()-1);
					if(_text.trim().contains(" ")){
						String[] values = _text.trim().split("\\s+");
						StringBuffer result = new StringBuffer();
						result.append("(");
						for(String value:values){
							if("OR".equals(value) || "AND".equals(value) || "NOT".equals(value)){
								result.append(value).append(" ");
							}else{
								result.append(lang).append("|").append(value).append(" ");
							}
						}
						result.append(")");
						return result.toString();
					}else{
						return "("+lang+"|"+_text+")";
					}
				}else if(_text.trim().contains(" ")){
					String[] values = _text.trim().split("\\s+");
					StringBuffer result = new StringBuffer();
					result.append("(");
					for(String value:values){
						if("OR".equals(value) || "AND".equals(value) || "NOT".equals(value)){
							result.append(value).append(" ");
						}else{
							result.append(lang).append("|").append(value).append(" ");
						}
					}
					result.append(")");
					return result.toString();
				}else{
					return lang + "|" + _text.trim();
				}
			}else {
				if(_text.startsWith("(") && _text.endsWith(")")){
					_text = _text.substring(1,_text.length()-1);
					return "(" + lang + "|" + _text + ")";
				}else{
					return lang + "|" + _text;
				}
			}
		}
		return _text;
	}
	/**
	 * 多语种模式识别文本
	 * 
	 * @param _text
	 * 
	 * @return 返回语种的2位简称
	 */
	public static List<String> detectLangs(String _text) {
		// 初始化语言包
		loadLangProfiles();

		List<String> langList = new ArrayList<String>();
		Detector detect = null;
		try {
			detect = DetectorFactory.create();
			detect.append(_text);
			List<Language> list = detect.getProbabilities();
			if (CollectionUtils.isNotEmpty(list)) {
				for (Language language : list) {
					String languageTemp = language.lang;
					if (!whiteList.contains(languageTemp)) {
						languageTemp = fallback;
					}

					if (!langList.contains(languageTemp)) {
						langList.add(languageTemp);
					}
				}
			} else {
				langList.add(fallback);
			}
		} catch (LangDetectException e) {
			LOG.debug(UtilConstant.PROJECT + " 文本中未发现语言特征.");
		}
		return langList;
	}

	/**
	 * 多语种模式识别文本,并包装返回,格式为en,zh-cn|文本内容
	 * 
	 * @param _text
	 * 
	 * @return 返回格式为 en,zh-cn|文本内容
	 */
	public static String detectLangsAndWrap(String _text) {
		List<String> langList = detectLangs(_text);
		if (CollectionUtils.isNotEmpty(langList) && StringUtils.isNotBlank(_text)) {
			return StringUtils.join(langList, ",") + "|" + _text;
		}
		return _text;
	}

	/**
	 * 返回支持的语种
	 * 
	 * @param _text
	 * 
	 * @return 返回语种的2位简称
	 */
	public static List<String> getLangList() {
		return DetectorFactory.getLangList();
	}

	/**
	 * @return the fallback
	 */
	public static String getFallback() {
		return fallback;
	}

	/**
	 * @param fallback
	 *            the fallback to set
	 */
	public static void setFallback(String fallback) {
		LangDetectUtils.fallback = fallback;
	}

	/**
	 * @return the languages
	 */
	public static String[] getLanguages() {
		return languages;
	}

	// ********************************************************************************************************
	/**
	 * 加载语种包
	 * 
	 * @param langs
	 */
	static synchronized void loadLangProfiles() {
		// 初始化语言包
		if (DetectorFactory.getLangList().size() == 0) {
			try {
				List<String> langList = new ArrayList<String>();
				for (String string : languages) {
					InputStream in = XMLUtils.convertToInputStream("langdetect_profiles/longtext/" + string);
					BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
					langList.add(new String(IOUtils.toCharArray(reader)));
					reader.close();
				}
				DetectorFactory.loadProfile(langList);
				DetectorFactory.setSeed(10);
			} catch (Exception e) {
				System.out.println("aaaa");
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
 
	}
}
